#ifndef XLCOMM_NET_TCPCLIENT_H_
#define XLCOMM_NET_TCPCLIENT_H_

#include <atomic>
#include <memory>
#include <mutex>

#include "xlcomm/define.h"
#include "xlcomm/net/callbacks.h"
#include "xlcomm/net/event_loop.h"
#include "xlcomm/net/inet_address.h"
#include "xlcomm/net/tcp_connection.h"
#include "xlcomm/noncopyable.h"

namespace xlcomm {
namespace net {

class Connector;
using ConnectorPtr = std::shared_ptr<Connector>;  // FIXME：不用shared_ptr

// TCP客户端
class XLCOMM_API TcpClient : noncopyable {
 public:
  TcpClient(EventLoop* loop, const InetAddress& server_addr,
            const std::string& name, bool retry = false);
  ~TcpClient();

  // 异步连接服务端（线程安全）
  void Connect();
  // 断开和服务端的连接（线程安全）
  void Disconnect();
  // 停止连接（线程安全）
  void Stop();

  EventLoop* loop() const { return loop_; }

  TcpConnectionPtr connection() const {
    std::lock_guard<std::mutex> guard(mutex_);
    return connection_;
  }

  // 注册连接建立后的回调（非线程安全）
  void set_connect_callback(const ConnectCallback& cb) {
    connect_callback_ = cb;
  }
  // 注册连接断开后的回调（非线程安全）
  void set_disconnect_callback(const DisconnectCallback& cb) {
    disconnect_callback_ = cb;
  }
  // 注册消息读出后的回调（非线程安全）
  void set_message_callback(const MessageCallback& cb) {
    message_callback_ = cb;
  }
  // 注册缓冲区消息写完后的回调（非线程安全）
  // 低流量应用可以不用关心这个事件
  void set_write_complete_callback(const WriteCompleteCallback& cb) {
    write_complete_callback_ = cb;
  }

 private:
  // 连接建立成功处理
  void NewConnection(int sockfd);
  // 移除连接
  void RemoveConnection(const TcpConnectionPtr& conn);

  EventLoop* loop_;
  std::string name_;
  uint64_t conn_id_;
  ConnectorPtr connector_;
  TcpConnectionPtr connection_;
  std::atomic<bool> will_connect_;
  bool retry_;
  mutable std::mutex mutex_;

  ConnectCallback connect_callback_;
  DisconnectCallback disconnect_callback_;
  MessageCallback message_callback_;
  WriteCompleteCallback write_complete_callback_;
};

}  // namespace net
}  // namespace xlcomm

#endif  // XLCOMM_NET_TCPCLIENT_H_